/***************************************************************
 *
 * (c) 2008 Markus Dittrich 
 *
 * This program is free software; you can redistribute it 
 * and/or modify it under the terms of the GNU General Public 
 * License Version 3 as published by the Free Software Foundation. 
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License Version 3 for more details.
 *
 * You should have received a copy of the GNU General Public 
 * License along with this program; if not, write to the Free 
 * Software Foundation, Inc., 59 Temple Place - Suite 330, 
 * Boston, MA 02111-1307, USA.
 *
 ****************************************************************/

/** STL includes */

/* Qt includes */
#include <QComboBox>
#include <QGridLayout>
#include <QGroupBox>
#include <QHBoxLayout>
#include <QKeyEvent>
#include <QLabel>
#include <QLineEdit>
#include <QPushButton>
#include <QString>
#include <QToolButton>
#include <QVBoxLayout>

/* local includes */
#include "data_label_widget.h"
#include "utilities.h"
#include "basic_definitions.h"

/* add names to local namespace */
using std::list;



//----------------------------------------------------------------
// constructor
//----------------------------------------------------------------
DataLabelWidget::DataLabelWidget(DataLabelManager& theLabels,
    QWidget* theParent)
  :
    QDialog(theParent),
    labelManager_(theLabels),
    currentMovableLabel_(MAIN_LABEL)
{
  setWindowTitle(tr("Edit Labels"));

  /* set up dimensions */
  setMinimumWidth(600);

  /* set up the widget */
  generate_main_layout_(); 
  generate_main_label_();
  generate_axis_labels_(); 
  generate_data_label_();
  generate_positioning_grouper_();
  generate_buttons_();

  setLayout(mainLayout_);

  /* some connections */
  connect(this, SIGNAL(update_canvas()), theParent,
      SLOT(redraw_canvas()));
}



/*****************************************************************
 *
 * private slots
 *
 *****************************************************************/

//----------------------------------------------------------------
// catch keypress events on this widget;
// ignore return to avoid that the position widget receive false 
// clicked() events.
// NOTE: This seems like a hack but works as far as I can tell
//----------------------------------------------------------------
void DataLabelWidget::keyPressEvent(QKeyEvent* anEvent)
{
  anEvent->accept();

  switch(anEvent->key())
  {
    case Qt::Key_Return:
      break;
    default:
      QWidget::keyPressEvent(anEvent);
  }
}



/*****************************************************************
 *
 * private slots
 *
 *****************************************************************/

//----------------------------------------------------------------
// update DataLabelManager with the entered axis/main labels 
//----------------------------------------------------------------
void DataLabelWidget::add_axis_labels_to_manager_()
{
  QString mainLabelText = mainLabelEdit_->text();
  labelManager_.set_label_name(MAIN_LABEL, mainLabelText);

  QString xAxisLabelText = xAxisLabelEdit_->text();
  labelManager_.set_label_name(X_AXIS_LABEL, xAxisLabelText);

  QString yAxisLabelText = yAxisLabelEdit_->text();
  labelManager_.set_label_name(Y_AXIS_LABEL, yAxisLabelText);

  /* tell our parent to update the canvas */
  emit update_canvas();
}


//----------------------------------------------------------------
// update DataLabelManager with the entered data labels 
//----------------------------------------------------------------
void DataLabelWidget::add_data_labels_to_manager_()
{
  /* retrieve the presently selected data label; we need
   * the full path stored in QVariant */
  int index = dataSelector_->currentIndex();
  QVariant dataNameVariant = dataSelector_->itemData(index);
  QString selectedDataName = dataNameVariant.toString();
  QString dataLabelText = dataLabelEdit_->text();

  labelManager_.set_data_label_name(selectedDataName, 
      dataLabelText);

  /* tell our parent to update the canvas */
  emit update_canvas();
}


//----------------------------------------------------------------
// retrieve the current label for the selected data set and 
// display it in the LineEdit widget
//----------------------------------------------------------------
void DataLabelWidget::retrieve_current_data_label_(int selectedData)
{
  QVariant dataNameVariant = dataSelector_->itemData(selectedData);
  QString selectedDataName = dataNameVariant.toString();
  QString currentLabel = 
    labelManager_.get_data_label(selectedDataName);

  dataLabelEdit_->setText(currentLabel);
}

  
//----------------------------------------------------------------
// update currently selected label for movement
//----------------------------------------------------------------
void DataLabelWidget::new_label_selected_(int newLabelSelection)
{
  QVariant item = labelSelector_->itemData(newLabelSelection);
  bool ok;
  int selection = item.toInt(&ok);
  
  /* make sure conversion was successfull, do nothing otherwise */
  if ( ok )
  {
    currentMovableLabel_ = selection;
  }

  return;
}


//----------------------------------------------------------------
// move selected label to the left
//----------------------------------------------------------------
void DataLabelWidget::left_move_button_pressed_()
{
  labelManager_.move_label_left(currentMovableLabel_);

  /* update canvas */
  emit update_canvas();
}

  
//----------------------------------------------------------------
// move selected label to the right
//----------------------------------------------------------------
void DataLabelWidget::right_move_button_pressed_()
{
  labelManager_.move_label_right(currentMovableLabel_);

  /* update canvas */
  emit update_canvas();
}


//----------------------------------------------------------------
// move selected label up
//----------------------------------------------------------------
void DataLabelWidget::up_move_button_pressed_()
{
  labelManager_.move_label_up(currentMovableLabel_);

  /* update canvas */
  emit update_canvas();
}


//----------------------------------------------------------------
// move selected label down
//----------------------------------------------------------------
void DataLabelWidget::down_move_button_pressed_()
{
  labelManager_.move_label_down(currentMovableLabel_);

  /* update canvas */
  emit update_canvas();
}


//----------------------------------------------------------------
// reset label position to its default
//----------------------------------------------------------------
void DataLabelWidget::reset_move_button_pressed_()
{
  labelManager_.reset_label(currentMovableLabel_);

  /* update canvas */
  emit update_canvas();
}


//----------------------------------------------------------------
// update coordinate widget triggered by any of the label 
// movement buttons
//----------------------------------------------------------------
void DataLabelWidget::update_coordinate_widget_()
{
  const QPoint& currentPos = 
  labelManager_.get_label_pos(currentMovableLabel_);
  QString xPos;
  xPos.setNum(currentPos.x());
  QString yPos;
  yPos.setNum(currentPos.y());

  xCoordinateEntry_->setText(xPos);
  yCoordinateEntry_->setText(yPos);
}
 

//----------------------------------------------------------------
// update the selected label coordinate after a coordinate was
// entered in one of the coodinate entry fields
//----------------------------------------------------------------
void DataLabelWidget::new_coordinate_entered_()
{
  QString xAxisCoordinate = xCoordinateEntry_->text();
  QString yAxisCoordinate = yCoordinateEntry_->text();

  QPoint newPos(xAxisCoordinate.toInt(), yAxisCoordinate.toInt());
  labelManager_.set_label_pos(currentMovableLabel_,newPos);

  /* update canvas */
  emit update_canvas();
}
  
  
/*****************************************************************
 *
 * private member functions
 *
 *****************************************************************/

//----------------------------------------------------------------
// generate the main layout 
//----------------------------------------------------------------
void DataLabelWidget::generate_main_layout_()
{
  mainLayout_ = new QVBoxLayout;
  mainLabelLayout_ = new QGridLayout;

  mainLayout_->addLayout(mainLabelLayout_);
}


//----------------------------------------------------------------
// generate the main label entry widget 
//----------------------------------------------------------------
void DataLabelWidget::generate_main_label_()
{
  QLabel* mainLabelText = new QLabel(tr("main label"));
  const QString& previousMainLabel = 
    labelManager_.get_axis_label(MAIN_LABEL);
  mainLabelEdit_ = new QLineEdit(previousMainLabel);
  mainLabelText->setBuddy(mainLabelEdit_);
  
  mainLabelLayout_->addWidget(mainLabelText, 0, 0);
  mainLabelLayout_->addWidget(mainLabelEdit_, 0, 1);

  connect(mainLabelEdit_,SIGNAL(returnPressed()),this,
      SLOT(add_axis_labels_to_manager_()));
}

  
//----------------------------------------------------------------
// generate the x and y axis label entry widget 
//----------------------------------------------------------------
void DataLabelWidget::generate_axis_labels_()
{
  QLabel* xAxisLabelText = new QLabel(tr("x axis label"));
  const QString& previousXLabel = 
    labelManager_.get_axis_label(X_AXIS_LABEL);
  xAxisLabelEdit_ = new QLineEdit(previousXLabel);
  xAxisLabelText->setBuddy(xAxisLabelEdit_);

  mainLabelLayout_->addWidget(xAxisLabelText, 1, 0);
  mainLabelLayout_->addWidget(xAxisLabelEdit_, 1, 1);
  connect(xAxisLabelEdit_,SIGNAL(returnPressed()),this,
      SLOT(add_axis_labels_to_manager_()));

  QLabel* yAxisLabelText = new QLabel(tr("y axis label"));
  const QString& previousYLabel = 
    labelManager_.get_axis_label(Y_AXIS_LABEL);
  yAxisLabelEdit_ = new QLineEdit(previousYLabel);
  yAxisLabelText->setBuddy(yAxisLabelEdit_);

  mainLabelLayout_->addWidget(yAxisLabelText, 2, 0);
  mainLabelLayout_->addWidget(yAxisLabelEdit_, 2, 1);
  connect(yAxisLabelEdit_,SIGNAL(returnPressed()),this,
      SLOT(add_axis_labels_to_manager_()));
}


//----------------------------------------------------------------
// generate the main label entry widget 
// NOTE: We store the full path in a QVariant and only use
// the filename for the combo box itself for better visibility
//----------------------------------------------------------------
void DataLabelWidget::generate_data_label_()
{
  /* add QComboBox with available data set names */ 
  dataSelector_ = new QComboBox;
  dataLabelEdit_ = new QLineEdit;

  const list<QString>& dataNames = 
    labelManager_.get_data_label_names();
  FOREACH(QString name, dataNames)
  {
    dataSelector_->addItem(strip_path(name),name);
  }

  /* add previous label */
  retrieve_current_data_label_(dataSelector_->currentIndex());

  mainLabelLayout_->addWidget(dataSelector_, 3, 0);
  mainLabelLayout_->addWidget(dataLabelEdit_, 3, 1);

  connect(dataLabelEdit_,SIGNAL(returnPressed()),this,
      SLOT(add_data_labels_to_manager_()));
  connect(dataSelector_,SIGNAL(currentIndexChanged(int)),
      this,SLOT(retrieve_current_data_label_(int)));
}
 

//----------------------------------------------------------------
// generate widget to allow positioning of the labels on 
// the canvas 
//----------------------------------------------------------------
void DataLabelWidget::generate_positioning_grouper_()
{
  QGroupBox* labelPositionGrouper_ = 
    new QGroupBox(tr("move selected label on canvas"));
  mainLayout_->addWidget(labelPositionGrouper_);
  QHBoxLayout* positionLayout = new QHBoxLayout;
  
  generate_label_selector_widget_(positionLayout);
  generate_motion_widget_(positionLayout);
  positionLayout->addSpacing(70);
  generate_label_position_widget_(positionLayout);
  positionLayout->addSpacing(30);

  /* put everything into place */
  labelPositionGrouper_->setLayout(positionLayout);
}


//---------------------------------------------------------------
// generate widget used to move the labels on the canvas 
//---------------------------------------------------------------
void DataLabelWidget::generate_label_selector_widget_(
    QHBoxLayout* positionLayout)
{
  QHBoxLayout* labelLayout = new QHBoxLayout;
  labelSelector_ = new QComboBox;
  populate_label_selector_();
  labelLayout->addWidget(labelSelector_);
  labelLayout->addStretch(1);

  positionLayout->addLayout(labelLayout);
}


//---------------------------------------------------------------
// generate widget used to move the labels on the canvas 
//---------------------------------------------------------------
void DataLabelWidget::generate_motion_widget_(
    QHBoxLayout* positionLayout)
{
  QGridLayout* motionLayout = new QGridLayout;

  QPushButton* leftMoveButton = new QPushButton;
  leftMoveButton->setIcon(QIcon(":/icons/left.png"));
  connect(leftMoveButton, SIGNAL(clicked()),this,
      SLOT(left_move_button_pressed_()));
  connect(leftMoveButton, SIGNAL(clicked()),this,
      SLOT(update_coordinate_widget_()));

  QPushButton* rightMoveButton = new QPushButton;
  rightMoveButton->setIcon(QIcon(":/icons/right.png"));
  connect(rightMoveButton, SIGNAL(clicked()),this,
      SLOT(right_move_button_pressed_()));
  connect(rightMoveButton, SIGNAL(clicked()),this,
      SLOT(update_coordinate_widget_()));

  QPushButton* upMoveButton = new QPushButton;
  upMoveButton->setIcon(QIcon(":/icons/up.png"));
  connect(upMoveButton, SIGNAL(clicked()),this,
      SLOT(up_move_button_pressed_()));
  connect(upMoveButton, SIGNAL(clicked()),this,
      SLOT(update_coordinate_widget_()));

  QPushButton* downMoveButton = new QPushButton;
  downMoveButton->setIcon(QIcon(":/icons/down.png"));
  connect(downMoveButton, SIGNAL(clicked()),this,
      SLOT(down_move_button_pressed_()));
  connect(downMoveButton, SIGNAL(clicked()),this,
      SLOT(update_coordinate_widget_()));

  QPushButton* resetMoveButton = new QPushButton;
  resetMoveButton->setIcon(QIcon(":/icons/gohome.png"));
  connect(resetMoveButton, SIGNAL(clicked()),this,
      SLOT(reset_move_button_pressed_()));
  connect(resetMoveButton, SIGNAL(clicked()),this,
      SLOT(update_coordinate_widget_()));

  motionLayout->addWidget(upMoveButton,0,1);
  motionLayout->addWidget(leftMoveButton,1,0);
  motionLayout->addWidget(resetMoveButton,1,1);
  motionLayout->addWidget(rightMoveButton,1,2);
  motionLayout->addWidget(downMoveButton,2,1);
  positionLayout->addLayout(motionLayout);
 }


//---------------------------------------------------------------
// generate widget used to move the labels on the canvas 
//---------------------------------------------------------------
void DataLabelWidget::generate_label_position_widget_(
    QHBoxLayout* positionLayout)
{
  QGridLayout* currentPositionLayout = new QGridLayout;

  /* retrieve current position */
  const QPoint& currentPos = 
    labelManager_.get_label_pos(currentMovableLabel_);
  QString xPos;
  xPos.setNum(currentPos.x());
  QString yPos;
  yPos.setNum(currentPos.y());

  /* x coordinate */
  QLabel* xCoordinate = new QLabel(tr("x"));
  xCoordinateEntry_ = new QLineEdit(xPos);
  connect(xCoordinateEntry_,SIGNAL(returnPressed()),
      this,SLOT(new_coordinate_entered_()));

  QLabel* yCoordinate = new QLabel(tr("y"));
  yCoordinateEntry_ = new QLineEdit(yPos);
  connect(yCoordinateEntry_,SIGNAL(returnPressed()),
    this,SLOT(new_coordinate_entered_()));

  currentPositionLayout->addWidget(xCoordinate,0,0);
  currentPositionLayout->addWidget(xCoordinateEntry_,0,1);
  currentPositionLayout->addWidget(yCoordinate,1,0);
  currentPositionLayout->addWidget(yCoordinateEntry_,1,1);
  positionLayout->addLayout(currentPositionLayout); }
 

//----------------------------------------------------------------
// generate buttons at the bottom of the widget 
//----------------------------------------------------------------
void DataLabelWidget::generate_buttons_()
{
  QHBoxLayout* buttonLayout = new QHBoxLayout;
  QPushButton* cancelButton = new QPushButton(tr("close"));
  cancelButton->setShortcut(tr("Esc"));

  buttonLayout->addStretch();
  buttonLayout->addWidget(cancelButton);

  mainLayout_->addLayout(buttonLayout);
  connect(cancelButton, SIGNAL(clicked()), this, SLOT(close()));
}


//-----------------------------------------------------------------
// add available labels to selector for changing label positions
// We use per item QVariants to take proper actions based on 
// the selection
//-----------------------------------------------------------------
void DataLabelWidget::populate_label_selector_()
{
  QVariant mainLabelVariant(MAIN_LABEL);
  labelSelector_->addItem(tr("main label"), mainLabelVariant);
  labelSelector_->setCurrentIndex(0);

  QVariant xAxisLabelVariant(X_AXIS_LABEL);
  labelSelector_->addItem(tr("x axis label"), xAxisLabelVariant);

  QVariant yAxisLabelVariant(Y_AXIS_LABEL);
  labelSelector_->addItem(tr("y axis label"), yAxisLabelVariant);

  QVariant dataLabelVariant(DATA_LABEL);
  labelSelector_->addItem(tr("data label"), dataLabelVariant);

  connect(labelSelector_, SIGNAL(currentIndexChanged(int)),
      this, SLOT(new_label_selected_(int)));
  connect(labelSelector_, SIGNAL(currentIndexChanged(int)),
      this, SLOT(update_coordinate_widget_()));
}
    






  
